-module(katzenreis_utils).

-export([escape_html/1, escape_quotes/1, file_open_error/2,
  is_string/1, print/1, to_bool/1, to_integer/2, unquote_string/1]).

-include("katzenreis.hrl").
        

file_open_error(Path, Reason) ->
  throw({error, "cannot open file `"++Path++"' ("++Reason++")"}).


%% @doc Returns `true' if an argument is a string which is
%% a list contains only ASCII characters, or `false'.
%% @spec (term()) -> boolean()
%% @since #since

-spec is_string(term()) -> boolean().

is_string([]) -> true;
is_string([C|S]) ->
  case 0 =< C andalso C =< 255 of
    true -> is_string(S);
    false -> false
  end;
is_string(_) -> false.


%% @doc Returns `true' if the argument is not `false' and an empty list,
%%  otherwise `false'.
%% @spec (term()) -> bool()
%% @since #since

-spec to_bool(term()) -> bool().

to_bool(false) -> false;
to_bool([]) -> false;
to_bool(_) -> true.


%% @doc Converts `Value' to an integer value.
%%  If `Value' is a float value, returns rounded integer value.
%%  If this function cannot convert `Value', returns `Default'.
%% @spec (Value::term(), Default::term()) -> integer()
%% @since #since

-spec to_integer(term(), term()) -> integer().

to_integer(N, _Default) when is_integer(N) -> N;
to_integer(N, _Default) when is_float(N) -> round(N);
to_integer(L, Default) when is_list(L) ->
  try list_to_integer(L) of
    N -> N
  catch
    _:_ -> Default
  end.


%% @doc Returns text representation for `Term'.
%%  <dl>
%%  <dt><code>list()</code></dt>
%%  <dd>An empty list is converted to an empty string.</dd>
%%  </dl>
%% @spec (term()) -> string()
%% @since #since

-spec print(term()) -> string().

print([]) -> "";
print(Term) ->
  case is_string(Term) of
    true -> Term;
    false -> lists:flatten(io_lib:print(Term))
  end.


%% @doc Returns a string which is removed double quotes of both sides of
%%  `String', and is unespaced backslash-escaped control characters.
%% @spec (String::string()) -> string()
%% @since #since

-spec unquote_string(string()) -> string().

unquote_string(Str) ->
  Content = string:substr(Str, 2, length(Str)-2),
  unquote_string(Content, []).

unquote_string([], Result) -> lists:reverse(Result);
unquote_string("\\\""++Str, Result) -> unquote_string(Str, [$"|Result]);
unquote_string("\\r"++Str, Result) -> unquote_string(Str, [$\r|Result]);
unquote_string("\\n"++Str, Result) -> unquote_string(Str, [$\n|Result]);
unquote_string("\\f"++Str, Result) -> unquote_string(Str, [$\f|Result]);
unquote_string("\\t"++Str, Result) -> unquote_string(Str, [$\t|Result]);
unquote_string("\\v"++Str, Result) -> unquote_string(Str, [$\v|Result]);
unquote_string([Char|Str], Result) -> unquote_string(Str, [Char|Result]).


%% @doc Returns a string which escapes HTML control characters
%%  ("&amp;", "&lt;", "&gt;").
%% @spec (string() | atom() | binary()) -> string()
%% @since #since

-spec escape_html(string() | atom() | binary()) -> string().

escape_html(B) when is_binary(B) ->
    escape_html(binary_to_list(B), []);
escape_html(A) when is_atom(A) ->
    escape_html(atom_to_list(A), []);
escape_html(S) when is_list(S) ->
    escape_html(S, []).

escape_html([], Accu) ->
    lists:flatten(lists:reverse(Accu));
escape_html([$<|Rest], Accu) ->
    escape_html(Rest, ["&lt;"|Accu]);
escape_html([$>|Rest], Accu) ->
    escape_html(Rest, ["&gt;"|Accu]);
escape_html([$&|Rest], Accu) ->
    escape_html(Rest, ["&amp;"|Accu]);
escape_html([C|Rest], Accu) ->
    escape_html(Rest, [C|Accu]).


%% @doc Returns a string which espaces double quotes by adding backslash.
%% @spec (string()) -> string()
%% @since #since

-spec escape_quotes(string()) -> string().

escape_quotes(S) -> escape_quotes(S, []).

escape_quotes([], Accu) -> lists:flatten(lists:reverse(Accu));
escape_quotes([$"|S], Accu) -> escape_quotes(S, ["\\\""|Accu]);
escape_quotes([C|S], Accu) -> escape_quotes(S, [C|Accu]).

